/**
 * @FileName: SmsdboServiceDefinitionParser.java
 * @Package: com.ziroom.sms.std.spring
 * @author liusq23
 * @created 2017/6/13 下午6:01
 * <p>
 * Copyright 2015 ziroom
 */
package com.ziroom.sms.std.spring;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;

import java.util.List;

/**
 * <p>
 * 解析smsdbo标签
 * </p>
 * <PRE>
 * <BR>	修改记录
 * <BR>-----------------------------------------------
 * <BR>	修改日期			修改人			修改内容
 * </PRE>
 *
 * @author liusq23
 * @version 1.0
 * @since 1.0
 */
public class SmsdboServiceDefinitionParser implements BeanDefinitionParser {

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        builder.setLazyInit(true);
        builder.getBeanDefinition().setBeanClass(getBeanClass(element));
        return parseService(element, parserContext, builder);
    }

    protected Class<?> getBeanClass(Element element) {
        return ServiceBean.class;
    }

    /**
     * 解析dubbo标签，设置beanId 为interfaceName
     *
     * @param element
     * @param parseContext
     * @param builder
     */
    protected BeanDefinition parseService(Element element, ParserContext parseContext, BeanDefinitionBuilder builder) {
        String ref = element.getAttribute("ref");
        builder.addPropertyReference("ref", ref);
        String interfaceName = element.getAttribute("interface");
        builder.addPropertyValue("interfaceName", interfaceName);
        try {
            builder.addPropertyValue("interfaceClass", Class.forName(interfaceName));
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException(e);
        }
        String protocol = element.getAttribute("protocol");
        builder.addPropertyValue("protocol", protocol);
        List<Element> methodList = DomUtils.getChildElementsByTagName(element, "method");
        builder.addPropertyValue("methods", parseMethods(methodList));
        int counter = 2;
        while (parseContext.getRegistry().containsBeanDefinition(interfaceName)) {
            interfaceName = interfaceName + (counter++);
        }
        builder.addPropertyValue("id", interfaceName);
        builder.addPropertyValue("beanName",interfaceName);
        BeanDefinition beanDefinition = builder.getBeanDefinition();
        parseContext.getRegistry().registerBeanDefinition(interfaceName, beanDefinition);
        return beanDefinition;
    }

    /**
     * @param methodList
     * @return
     */
    private ManagedList<BeanDefinition> parseMethods(List<Element> methodList) {
        ManagedList<BeanDefinition> childrenMethods = new ManagedList<>(methodList.size());
        for (Element element : methodList) {
            childrenMethods.add(parseMethod(element));
        }
        return childrenMethods;
    }

    /**
     * parsemethod
     *
     * @param element
     * @return
     */
    private BeanDefinition parseMethod(Element element) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(MethodConfig.class);
        String name = element.getAttribute("name");
        builder.addPropertyValue("name", name);
        String timeout = element.getAttribute("timeout");
        builder.addPropertyValue("timeout", timeout);
        String retries = element.getAttribute("retries");
        builder.addPropertyValue("retries", retries);
        return builder.getBeanDefinition();
    }

}
